﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rappelz.GameServer
{
    public class MemoryPool
    {
        private static uint m_misctop = 0x20000001;
        private static uint m_mobtop = 0x40000001;
        private static uint m_playertop = 0x80000001;
        private static uint m_summontop = 0xC0000001;
        private static uint m_pettop = 0xE0000001;
        private static uint m_itemtop = 0x00000001;

        private static Dictionary<uint, GameObject> m_hsMisc = new Dictionary<uint, GameObject>();
        private static Dictionary<uint, Monster> m_hsMobs = new Dictionary<uint, Monster>();
        private static Dictionary<uint, Player> m_hsPlayers = new Dictionary<uint, Player>();
        private static Dictionary<uint, Summon> m_hsSummons = new Dictionary<uint, Summon>();
        private static Dictionary<uint, Pet> m_hsPets = new Dictionary<uint, Pet>();
        private static Dictionary<uint, Item> m_hsItems = new Dictionary<uint, Item>();

        public static void Init()
        {

        }

        public static GameObject getPtrFromId(uint uid)
        {
            GameObject result;

            uint idbase = uid & 0xE0000000;
            if (idbase != 0)
            {
                switch (idbase)
                {
                    case 0x20000000:
                        result = getMiscPtrFromId(uid);
                        break;
                    case 0x40000000:
                        result = (GameObject)getMonsterPtrFromId(uid);
                        break;
                    case 0x80000000:
                        result = (GameObject)getPlayerPtrFromId(uid);
                        break;
                    case 0xC0000000:
                        result = (GameObject)getSummonPtrFromId(uid);
                        break;
                    case 0xE0000000:
                        result = (GameObject)getPetPtrFromId(uid);
                        break;
                    default:
                        result = null;
                        break;
                }
            }
            else
            {
                result = (GameObject) getItemPtrFromId(uid);
            }
            return result;
        }

        public static GameObject getMiscPtrFromId(uint uid)
        {
            lock(m_hsMisc)
            {
                if (m_hsMisc.ContainsKey(uid))
                    return m_hsMisc[uid];
            }
            return null;
        }

        public static Monster getMonsterPtrFromId(uint uid)
        {
            lock(m_hsMobs)
            {
                if (m_hsMobs.ContainsKey(uid))
                    return m_hsMobs[uid];
            }
            return null;
        }

        public static Player getPlayerPtrFromId(uint uid)
        {
            lock(m_hsPlayers)
            {
                if (m_hsPlayers.ContainsKey(uid))
                    return m_hsPlayers[uid];
            }
            return null;
        }

        public static Summon getSummonPtrFromId(uint uid)
        {
            lock(m_hsSummons)
            {
                if (m_hsSummons.ContainsKey(uid))
                    return m_hsSummons[uid];
            }
            return null;
        }

        public static Pet getPetPtrFromId(uint uid)
        {
            lock(m_hsPets)
            {
                if (m_hsPets.ContainsKey(uid))
                    return m_hsPets[uid];
            }
            return null;
        }

        public static Item getItemPtrFromId(uint uid)
        {
            lock(m_hsItems)
            {
                if (m_hsItems.ContainsKey(uid))
                    return m_hsItems[uid];
            }
            return null;
        }

        public static Pet AllocPet()
        {
            Pet p = new Pet();
            p.m_hHandle = m_pettop;
            m_pettop++;
            m_hsPets.Add(p.m_hHandle, p);
            return p;
        }

        public static Player AllocPlayer()
        {
            Player p = new Player(m_playertop);
            p.m_hHandle = m_playertop;
            m_playertop++;
            m_hsPlayers.Add(p.m_hHandle, p);
            return p;
        }

        public static Monster AllocMonster(uint idx)
        {
            MonsterBase mb = GameContent.GetMonsterInfo(idx);
            if (mb == null)
                return null;
            lock(m_hsMobs)
            {
                Monster p = new Monster(m_mobtop, mb);
                p.m_hHandle = m_mobtop;
                m_mobtop++;
                m_hsMobs.Add(p.m_hHandle, p);
                return p;
            }
        }

        public static Item AllocGold(long gold, ItemInstance.GenerateCode gcode)
        {
            return Item.AllocItem(0,0,gold,gcode,0,-1,-1,-1,0,0,0,0,-1,0,0,0,0);
        }



        public static Item AllocItem()
        {
            Item p = new Item();
            lock(m_hsItems)
            {
                p.m_hHandle = m_itemtop;
                m_itemtop++;
                m_hsItems.Add(p.m_hHandle, p);
            }
            return p;
        }

        public static uint AllocItemId(Item item)
        {
            lock (m_hsItems)
            {
                item.m_hHandle = m_itemtop;
                item.m_Instance.UID = Player.allocItemUID();
                m_itemtop++;
                m_hsItems.Add(item.m_hHandle, item);
            }
            return m_itemtop-1;
        }

        public static uint AllocSummonId(Summon s)
        {
            lock (m_hsSummons)
            {
                s.m_hHandle = m_summontop;
                m_summontop++;
                m_hsSummons.Add(s.m_hHandle, s);
            }
            return m_summontop-1;
        }

        public static void AllocMiscHandle(GameObject obj)
        {
            lock (m_hsMisc)
            {
                obj.m_hHandle = m_misctop;
                m_misctop++;
                m_itemtop++;
                m_hsMisc.Add(obj.m_hHandle, obj);
            }
        }

        public static Skill AllocSkill(Creature pOwner, int uid, int id)
        {
            Skill result = new Skill(pOwner, uid,id);
            return result;
        }

        public static Summon AllocNewSummon(Player pMaster, Item pCard)
        {
            string name;

            Summon s = Summon.AllocSummon(pMaster, (uint)pCard.m_pItemBase.nSummonId);
            s.m_nSID = Player.allocSummonUID();
            s.SetLevel(1);
            s.CalculateStat();
            s.m_item = pCard;
            Summon.CalculateInitialJP(pCard, s);
            if (Globals.GetRandomInt32() % 100 >= 1)
            {
                name = GameContent.GetSummonName();
                s.SetName(name);
            }
            else
            {
                name = GameContent.GetUniqueName(s.GetCreatureGroup());
                s.SetName(name);
            }
            pCard.m_Instance.Socket[0] = s.m_nSID;
            pCard.m_bIsNeedUpdateToDB = true;
            pCard.m_pSummon = s;
            return s;
        }

        public static Pet AllocNewPet(Player pMaster, Item pCage, int nPetCode)
        {
            Pet p = Pet.AllocPet(pMaster, (uint)nPetCode);

            if (p != null)
            {
                p.m_nSID = Player.allocPetUID();
                p.m_item = pCage;
                p.SetName(p.m_ContentInfo.name_id);
                p.m_bNameChanged = ((p.m_ContentInfo.attribute_flag & 1) == 0);
                p.m_StatusFlag |= Creature.StatusFlags.LoginComplete;
                pCage.m_Instance.Socket[0] = p.m_nSID;
                pCage.m_Instance.Socket[1] = nPetCode;
                pCage.m_pPet = p;
                pCage.m_bIsNeedUpdateToDB = true;
                pCage.m_Instance.Flag |= 0x20;
            }
            return p;
        }

        public static int GetMonsterCount(int code)
        {
            int r = 0;
            lock (m_hsMobs)
            {
                foreach (KeyValuePair<uint,Monster> kvp in m_hsMobs)
                {
                    if (kvp.Value.m_pContentInfo.uid == code && kvp.Value.bIsInWorld)
                        r++;
                }
            }
            return r;
        }

        public static int GetMonsterCountFromParent(int code, uint hParent)
        {
            int r = 0;
            lock (m_hsMobs)
            {
                foreach (KeyValuePair<uint, Monster> kvp in m_hsMobs)
                {
                    if (kvp.Value.m_pContentInfo.uid == code && kvp.Value.bIsInWorld && kvp.Value.m_hParent == hParent)
                        r++;
                }
            }
            return r;
        }

    }
}
